package com.hup.utils.swing.customView.viewTable;

import lombok.extern.log4j.Log4j2;

import javax.swing.*;
import javax.swing.border.Border;
import javax.swing.border.EmptyBorder;
import javax.swing.plaf.UIResource;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.TableCellRenderer;
import java.awt.*;
import java.text.DateFormat;
import java.text.NumberFormat;

/**
 * 实现控制行颜色功能
 * 代码来自 {@link JTable}
 *
 * @author hugan
 * @date 2020/2/9
 */
@Log4j2
@SuppressWarnings("serial")
public class ColorCellRenderer {

    public interface ColorMatcher<R extends ViewTableRowBo<R>> {
        /**
         * @param row modelIndex
         * @param column modelIndex
         */
        ColorLevel getColorOf(ViewTable<R> table, int row, int column);
    }

    public enum ColorLevel {
        /**
         * 一般行颜色
         */
        NORMAL(null, null),
        /**
         * 强调色:()
         */
        STRONG(Color.LIGHT_GRAY, new Color(255, 171, 87)),
        /**
         * 警告色:(灰色,红色)
         */
        WARN(Color.LIGHT_GRAY, Color.RED),;

        private final Color notSelect;
        private final Color selected;

        ColorLevel(Color notSelect, Color selected) {
            this.notSelect = notSelect;
            this.selected = selected;
        }
    }

    /**
     * 实现条件行背景色的渲染器
     */
    public static class RowColorRenderer<R extends ViewTableRowBo<R>> extends DefaultTableCellRenderer {

        private ColorMatcher matcher;

        public RowColorRenderer(ColorMatcher<R> matcher) {
            this.matcher = matcher;
        }

        @SuppressWarnings("unchecked")
        @Override
        public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus,
                int row, int column) {
            Component res;//选中状态会影响setBackground的前后逻辑!!
            ColorLevel colorLevel = matcher.getColorOf((ViewTable<R>) table, table.convertRowIndexToModel(row), table.convertColumnIndexToModel(column));
            if (colorLevel == ColorLevel.NORMAL) {
                setBackground(null);//看源码逻辑需要设为null
                res = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
            } else {
                res = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
                setBackground(!isSelected ? colorLevel.notSelect : colorLevel.selected);
            }
            return res;
        }

        @SuppressWarnings("unchecked")
        public static class UIResource extends RowColorRenderer implements javax.swing.plaf.UIResource {
            public UIResource(ColorMatcher matcher) {
                super(matcher);
            }
        }
    }

    public static class NumberRenderer extends RowColorRenderer.UIResource {
        public NumberRenderer(ColorMatcher matcher) {
            super(matcher);
            setHorizontalAlignment(JLabel.RIGHT);
        }
    }

    public static class DoubleRenderer extends NumberRenderer {
        NumberFormat formatter;

        public DoubleRenderer(ColorMatcher matcher) {
            super(matcher);
        }

        public void setValue(Object value) {
            if (formatter == null) {
                formatter = NumberFormat.getInstance();
            }
            setText((value == null) ? "" : formatter.format(value));
        }
    }

    public static class DateRenderer extends RowColorRenderer.UIResource {
        DateFormat formatter;

        public DateRenderer(ColorMatcher matcher) {
            super(matcher);
        }

        public void setValue(Object value) {
            if (formatter == null) {
                formatter = DateFormat.getDateInstance();
            }
            setText((value == null) ? "" : formatter.format(value));
        }
    }

    public static class IconRenderer extends RowColorRenderer.UIResource {
        public IconRenderer(ColorMatcher matcher) {
            super(matcher);
            setHorizontalAlignment(JLabel.CENTER);
        }

        public void setValue(Object value) {
            setIcon((value instanceof Icon) ? (Icon) value : null);
        }
    }

    public static class BooleanRenderer<R extends ViewTableRowBo<R>> extends JCheckBox implements TableCellRenderer, UIResource {
        private static final Border noFocusBorder = new EmptyBorder(1, 1, 1, 1);
        private ColorMatcher matcher;

        public BooleanRenderer(ColorMatcher matcher) {
            this.matcher = matcher;
            setHorizontalAlignment(JLabel.CENTER);
            setBorderPainted(true);
        }

        @SuppressWarnings("unchecked")
        @Override
        public Component getTableCellRendererComponent(JTable table, Object value,
                boolean isSelected, boolean hasFocus, int row, int column) {

            ColorLevel colorLevel = matcher.getColorOf((ViewTable<R>) table, table.convertRowIndexToModel(row), table.convertColumnIndexToModel(column));

            if (isSelected) {
                setForeground(table.getForeground());
                setBackground(colorLevel == ColorLevel.NORMAL? table.getSelectionBackground() : colorLevel.selected);
            } else {
                setForeground(table.getForeground());
                setBackground(colorLevel == ColorLevel.NORMAL? table.getBackground() : colorLevel.notSelect);
            }
            setSelected((value != null && (Boolean) value));

            if (hasFocus) {
                setBorder(UIManager.getBorder("Table.focusCellHighlightBorder"));
            } else {
                setBorder(noFocusBorder);
            }

            return this;
        }
    }

}
